home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
dskut
/
errmon.zip
/
ERRMON.ASM
next >
Wrap
Assembly Source File
|
1985-08-30
|
9KB
|
378 lines
name ERRMON ;version 1.1
page 60,132
comment *
monitors INT 13 disk i/o and reports any errors encountered;
version 1.1 also reports the offending command
and the drive, cylinder, head, sector and number of sectors requested
AT disk change error is ignored
*
.radix 16
attribute equ 0f ;video attribute for error message
line equ 24d ;line for error message, 0-24
cr equ 0dh
lf equ 0a
com_org equ 100 ;ORG for com files
; error codes from IBM bios listings
sense_fail equ 0ff ;not implemented on AT
no_error equ 0e0 ;not implemented on PC, XT
write_fault equ 0cc ;not implemented on PC, XT
undef_err equ 0bbh
not_rdy equ 0aa ;not implemented on PC, XT
time_out equ 80
bad_seek equ 40
bad_cntlr equ 20
data_corrected equ 11
bad_eec equ 10
bad_track equ 0bh ;not implemented on AT
bad_sector equ 0a ;not implemented on PC, XT
dma_boundry equ 9
bad_dma equ 8
init_fail equ 7
media_change equ 6 ;ignore this AT error
bad_reset equ 5
record_not_fnd equ 4
write_protect equ 3
bad_addr_mark equ 2
bad_cmd equ 1
popff macro ;simulate POPF to avoid any '286 problems
jmp short $+3 ;jump around IRET
iret ;pops IP, CS, FLAGS
push cs ;CS to stack
call cs:$-2 ;IP to stack (cs: avoids masm error)
endm
entry struc ;map each entry in the error table
err_nmbr db ? ;error code number for this entry
msg_offset dw ? ;offset to message text for this error
msg_len db ? ;length of the message text
entry ends
stack struc ;stack structure
cur_loc dw ? ;save cursor location
reg_bp dw ?
reg_di dw ?
reg_si dw ?
reg_dx dw ? ;cx and dx hold the
reg_cx dw ? ; drive, cylinder, head, sector info
reg_bx dw ?
reg_ax dw ?
reg_f dw ? ;cy if error, code in ah
stack ends
errmon segment para public 'CODE'
assume cs:errmon
org com_org
start: jmp init ;go install
err_tbl db sense_fail
dw msg_ff
db len_ff
db no_error
dw msg_e0
db len_e0
db write_fault
dw msg_cc
db len_cc
ude db undef_err
dw msg_bb
db len_bb
db not_rdy
dw msg_aa
db len_aa
db time_out
dw msg_80
db len_80
db bad_seek
dw msg_40
db len_40
db bad_cntlr
dw msg_20
db len_20
db data_corrected
dw msg_11
db len_11
db bad_eec
dw msg_10
db len_10
db bad_track
dw msg_0b
db len_0b
db bad_sector
dw msg_0a
db len_0a
db dma_boundry
dw msg_09
db len_09
db bad_dma
dw msg_08
db len_08
db init_fail
dw msg_07
db len_07
; db media_change ;ignore this AT error
; dw msg_06
; db len_06
db bad_reset
dw msg_05
db len_05
db record_not_fnd
dw msg_04
db len_04
db write_protect
dw msg_03
db len_03
db bad_addr_mark
dw msg_02
db len_02
db bad_cmd
dw msg_01
db len_01
nmbr_errs equ ($-err_tbl)/size entry
msg_ff db 'Sense failure'
len_ff equ $-msg_ff
msg_e0 db 'Status error'
len_e0 equ $-msg_e0
msg_cc db 'Write fault'
len_cc equ $-msg_cc
msg_bb db 'Undefined error'
len_bb equ $-msg_bb
msg_aa db 'Drive not ready'
len_aa equ $-msg_aa
msg_80 db 'No response'
len_80 equ $-msg_80
msg_40 db 'Seek failure'
len_40 equ $-msg_40
msg_20 db 'Controller failure'
len_20 equ $-msg_20
msg_11 db 'EEC error corrected'
len_11 equ $-msg_11
msg_10 db 'Bad CRC/EEC on read'
len_10 equ $-msg_10
msg_0b db 'Bad track'
len_0b equ $-msg_0b
msg_0a db 'Bad sector'
len_0a equ $-msg_0a
msg_09 db 'DMA boundry crossed'
len_09 equ $-msg_09
msg_08 db 'DMA overrun'
len_08 equ $-msg_08
msg_07 db 'Drive init failure'
len_07 equ $-msg_07
;msg_06 db 'Disk changed' ;ignore this AT error
;len_06 equ $-msg_06
msg_05 db 'Drive reset failure'
len_05 equ $-msg_05
msg_04 db 'Sector not found'
len_04 equ $-msg_04
msg_03 db 'Disk write protected'
len_03 equ $-msg_03
msg_02 db 'DAM not found'
len_02 equ $-msg_02
msg_01 db 'Bad drive or command'
len_01 equ $-msg_01
msg_0 db ' ' ;display location of error sector
cmd db 2 dup (0)
db 'D'
drive db 2 dup (0)
db 'C'
cyl db 4 dup (0)
db 'H'
head db 2 dup (0)
db 'S'
sector db 2 dup (0)
db 'N'
number db 2 dup (0)
len_0 equ $-msg_0
int13 label dword
sav_int13 dw 2 dup(0) ;previous INT 13 vector
sav_ax dw 0 ;save command, number sectors requested
sav_col db 0 ;save number of screen columns
; INT 13 enters here
error proc far
pushf ;real INT 13 expects flags on stack
mov cs:[sav_ax],ax ;save command, number of sectors
call cs:[int13] ;do the real INT 13
jc chk_6 ;go if we have an error condition
ret 2 ;else discard caller's flags and return
chk_6: pushf ;save the flags from INT 13 for caller
cmp ah,media_change ;disk change error?
jne valid_err ;no
jmp exit ;yes, ignore it
; have a valid error, first save registers to be used
valid_err:
push ax ;ah = error code
push bx
push cx ;cl = sector and high bits of cylinder, ch = cylinder
push dx ;dl = drive, dh = head
push si
push di
push bp
; find the error in the table
mov di,offset err_tbl ;=> table
mov cx,nmbr_errs ;load number of errors in table
search: cmp ah,cs:[di].err_nmbr ;no SCAS, can't override ES register!
je found ;got a match
add di,size entry ;bump to next table entry
loop search
mov di,offset ude ;make it an undefined error
; find out where to print the report
found: mov ah,15d
int 10 ;get current mode, columns, page
mov cs:[sav_col],ah ;save for end of line check
sub ah,cs:[di].msg_len ;columns less msg_x
sub ah,len_0 ;less msg_0
jns len_ok ;if column >= 0
xor ah,ah ;else set column to 0
len_ok: mov al,ah ;starting column to al
mov ah,line ;row to ah
push ax ;save row, column to write to
mov bp,sp ;=> stack
; calculate the offending sector location
mov si,offset drive
mov ax,[bp].reg_dx
call cvt1 ;process drive number
mov si,offset head
mov al,ah
call cvt1 ;process head number
mov si,offset cyl
mov ax,[bp].reg_cx
mov bl,al ;save for later
and al,11000000b ;mask for high cyl bits
rol al,1
rol al,1 ;move to low nibble
call cvt1 ;process 1st part of cyl number
mov al,ah
call cvt1 ;process 2nd part of cyl number
mov si,offset sector
mov al,bl ;restore
and al,00111111b ;mask for sector number bits
call cvt1 ;process sector number
mov si,offset number
mov ax,cs:[sav_ax]
call cvt1 ;process number of sectors
mov si,offset cmd
mov al,ah
call cvt1 ;process command number
; write the report to the screen
mov ah,3
int 10 ;get current cursor position
xchg dx,[bp].cur_loc ;swap cursor positions
mov bl,attribute ;video attribute
mov cx,1 ;number characters to write
mov si,cs:[di].msg_offset ;=> msg_x
mov di,cs:[di].word ptr msg_len ;get len msg_x
and di,0000000011111111b ;need to clear high bits
call write ;write it
mov si,offset msg_0 ;=> msg_0
mov di,len_0 ;get len msg_0
call write ;write it
pop dx ;old cursor position
mov ah,2
int 10 ;restore cursor position
; now let caller do its thing with the error
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
exit: popff
ret 2 ;done, discard flags from caller
error endp
; convert hex byte in al to two ascii digits, store in si, si+1
cvt1 proc near
mov ch,al ;will need again
mov cl,4
shr al,cl ;high nibble to low
call cvt2 ;make it ascii and store
mov al,ch ;recover byte
and al,00001111b ;mask for low nibble
cvt2: add al,'0' ;make an ascii digit
cmp al,'9' ;need adjustment?
jbe no_adj ;nope
add al,7 ;adjust to A-F
no_adj: mov cs:[si],al ;stuff in msg_0
inc si ;bump pointer
ret
cvt1 endp
; write a defined length string to the screen
write proc near
cmp cs:[sav_col],dl ;end of line?
jbe no_wrt ;yes
mov ah,2
int 10 ;reset cursor position
inc dl ;bump column
mov al,cs:[si] ;get char to write
inc si ;bump pointer
mov ah,9
int 10 ;put it on screen
dec di ;decrement counter
jnz write ;if more to write
no_wrt: ret
write endp
pgm_len equ $-start+com_org ;rinky dink to get an absolute constant
remain equ pgm_len mod 10 gt 0 ;any remainder?
prot equ (pgm_len/10)-remain ;convert bytes to paragraphs, round